package com.zjw.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zjw.constants.SystemConstants;
import com.zjw.annotation.domain.ResponseResult;
import com.zjw.annotation.domain.entity.Menu;
import com.zjw.annotation.domain.vo.MenuListVo;
import com.zjw.annotation.domain.vo.MenuTreeListVo;
import com.zjw.annotation.domain.vo.RoleTreeMenuVo;
import com.zjw.enums.AppHttpCodeEnum;
import com.zjw.mapper.MenuMapper;
import com.zjw.service.MenuService;
import com.zjw.utils.BeanCopyUtils;
import io.jsonwebtoken.lang.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

/**
 * 菜单权限表(Menu)表服务实现类
 *
 * @author ljzy
 * @since 2023-12-20 11:33:20
 */
@Service("menuService")
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    @Autowired
    private MenuMapper menuMapper;


    @Override
    public List<Menu> getPermsById(Long id) {
        return menuMapper.getPermsById(id);
    }

    @Override
    public List<Menu> getTreeMenuById(Long id) {
        return menuMapper.getTreeMenuById(id);
    }

    @Override
    public List<Menu> getTreeMenuAdmin() {
        return menuMapper.getTreeMenuAdmin();
    }

    /**
     * 获取菜单列表 后台管理
     *
     * @param status   状态
     * @param menuName 菜单名称
     * @return {@link RestController}
     */
    @Override
    public ResponseResult getMenuList(String status, String menuName) {
        LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
        if (Strings.hasText(status)) {
            wrapper.eq(Menu::getStatus, status);
        }
        if (Strings.hasText(menuName)) {
            wrapper.like(Menu::getMenuName, menuName);
        }

        List<Menu> rawList = list(wrapper);
        List<MenuListVo> res = BeanCopyUtils.copyList(rawList, MenuListVo.class);

        return ResponseResult.okResult(res);
    }

    /**
     * 添加菜单
     *
     * @param menu 菜单
     * @return {@link ResponseResult}
     */
    @Override
    public ResponseResult addMenu(Menu menu) {
        save(menu);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult getMenuById(Long id) {
        Menu byId = getById(id);
        return ResponseResult.okResult(BeanCopyUtils.copy(byId, MenuListVo.class));
    }

    @Override
    public ResponseResult editMenu(Menu menu) {
        updateById(menu);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult removeMenu(Long id) {
        MenuMapper mapper = getBaseMapper();
//        判断是否是有子菜单的目录
        Menu menu = getById(id);
        if (menu == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_INVALID_CHECK);
        }

//        如果是菜单删除则要删除它之下的所有按钮
        if (menu.getMenuType().equals("M")) {
//            如果为目录，需要子目录非空
            Integer count = mapper.hasSub(menu.getId());
            if (count != 0)
                return ResponseResult.errorResult(AppHttpCodeEnum.MENU_HAS_SUB);
        }
        if (menu.getMenuType().equals("C")) {
//            菜单则删除它的所以子按钮
            List<Menu> subList = mapper.getSubBtn(id);
            subList.stream().forEach(m -> {
                doRemove(m.getId());
            });
        }
        doRemove(id);


//        删除菜单按钮是，要移除关系表中的关联
        return ResponseResult.okResult();
    }

    private void doRemove(Long id) {
//        删除指定id菜单 和 关系

//        移除关系
        MenuMapper mapper = getBaseMapper();
        mapper.removeFromRoleMenu(id);

//        删除菜单
        removeById(id);
    }


    /**
     * 获取树菜单列表 用于分配权限
     *
     * @return {@link ResponseResult}
     */
    @Override
    public ResponseResult getTreeMenuList() {
        LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Menu::getStatus, SystemConstants.MENU_NORMAL);
        List<Menu> raw = list(wrapper);

        List<MenuTreeListVo> res = new ArrayList<>();
        raw.stream().filter(m -> m.getParentId().equals(0L)).forEach(m -> {
            MenuTreeListVo temp = BeanCopyUtils.copy(m, MenuTreeListVo.class);
            temp.setLabel(m.getMenuName());
            temp.setChildren(getSubMenuList(raw, temp.getId()));
            res.add(temp);
        });
        return ResponseResult.okResult(res);
    }

    /**
     * 获取子菜单列表
     */
    public List<MenuTreeListVo> getSubMenuList(List<Menu> raw, Long pid) {
        List<MenuTreeListVo> res = new ArrayList<>();
        raw.stream().filter(m -> m.getParentId().equals(pid))
                .forEach(m -> {

                    MenuTreeListVo temp = BeanCopyUtils.copy(m, MenuTreeListVo.class);
                    temp.setLabel(m.getMenuName());
                    temp.setChildren(getSubMenuList(raw, temp.getId()));
                    res.add(temp);
                });
        return res;
    }

    /**
     * 分配角色身份验证
     *
     * @param id      编号
     * @param menuIds 菜单 ID
     */
    @Override
    public void assignRoleAuth(Long id, List<String> menuIds) {
        menuIds.stream().forEach(mId -> {
            menuMapper.assignAuth(id, (Long) Long.parseLong(mId));
        });
    }

    /**
     * 按 ID 获取角色菜单树
     *
     * @param id 编号
     * @return {@link ResponseResult}
     */
    @Override
    public ResponseResult getRoleMenuTreeById(Long id) {
//        获取所有可用权限菜单并组成成树状
        LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Menu::getStatus, SystemConstants.MENU_NORMAL);
        List<Menu> raw = list(wrapper);

        List<MenuTreeListVo> res = new ArrayList<>();
        raw.stream().filter(m -> m.getParentId().equals(0L)).forEach(m -> {
            MenuTreeListVo temp = BeanCopyUtils.copy(m, MenuTreeListVo.class);
            temp.setLabel(m.getMenuName());
            temp.setChildren(getSubMenuList(raw, temp.getId()));
            res.add(temp);
        });

        RoleTreeMenuVo resMenu = new RoleTreeMenuVo();
        resMenu.setMenus(res);
//        获取 指定角色的权限
        MenuMapper mapper = getBaseMapper();
        List<Menu> rawList = mapper.getRoleTreeById(id);
        List<String> checkedKeys = new ArrayList<>();

        rawList.stream().forEach(m->{
            checkedKeys.add(m.getId().toString());
        });
//        将权限列表组织成树状返回

        resMenu.setCheckedKeys(checkedKeys);
        return ResponseResult.okResult(resMenu);
    }


    /**
     * 按 ID 删除角色菜单
     *
     * @param id 编号
     */
    @Override
    public void removeRoleMenuById(Long id) {
        MenuMapper mapper = getBaseMapper();
        mapper.removeRoleMenuById(id);
    }
}

